iT邦幫忙

2026 iThome 鐵人賽

DAY 13
1
Software Development

1+1+1>3 ~ Spark 與 DataFusion、Comet 效能煉金術 ~系列 第 13

Day 13 DataFusion 可嵌入查詢引擎:為什麼還要再做一個

  • 分享至 

  • xImage
  •  

快到鐵人賽挑戰的一半了,我們從 D9 到 D12 走完儲存這一層,Parquet 內部剖了、了解了 Iceberg 四層漏斗、晚物化位圖跟 delete 交集也交代了。接下來剪枝後剩下要吐出去的那些列,資料就交給引擎這一層繼續跑,group by、join、sort、spill 都在這裡。

引擎這一層第一天要問一個聽起來很不友善的問題:

Spark、Presto、DuckDB、Photon 都在了,為什麼還要再做一個 DataFusion?

而且不是再做一個小玩具給論文用,而是 Apple、Meta、Uber、Databricks 都在拿它組裝自己的產品,Comet 更是把它直接塞回 Spark 當執行後端

今天不進 code,先把理解這個動機講,因為它決定了標題中「1+1+1>3」的其中一個 1 是什麼

先把「引擎」跟「資料庫」分開

日常講 MySQL 是資料庫,是把很多東西打包在一起,parser 把 SQL 變成 AST、optimizer 把 AST 變成執行計劃、executor 真的把資料撈出來算、storage 管檔案跟索引、transaction 管 ACID、client protocol 管網路,全部綁死在同一個 process。

查詢引擎是把中間那段挑出來:拿一個計劃,把資料算出來
不管前面 SQL 是誰 parse 的、後面資料存在哪、要用哪個網路協定回給誰。

一句話翻譯:

資料庫 = 引擎 + 儲存 + 交易 + 網路 + parser + 生態,全部一起賣。

引擎 = 只賣「把計劃算出來」這段。

DuckDB、SQLite 是資料庫(自己一整套)。DataFusion、Velox 是引擎(只賣中間那段),而 Spark 則是一半一半,前端跟優化器自己包,執行那段近年來一直想換掉(這也是 Comet 存在的原因)。

可嵌入到底是什麼意思

可嵌入(embeddable)這個詞比較模糊,拆成三個具體能力:

  1. 不用起 server:DataFusion 是一組 Rust crate,cargo add 進來就能在你的 process 裡跑 SQL,不用另外起一個 daemon、不用 JDBC、不用 network round trip,這個在前幾天介紹 datafusion-cli 中有提到過。
  2. 前端可以換掉:SQL 前端只是 DataFusion 的一個 crate,你可以自己寫一個 DataFrame API、GraphQL 前端、甚至用 Substrait 從別的系統送計劃進來
  3. 儲存可以換掉TableProvider 這個 trait 定義了「一個表格式要滿足什麼條件才能被引擎讀」,Iceberg、Delta、Hudi、你家 CDN 上的一堆 JSON 都可以接進來

三件事湊在一起,就是引擎跟前端跟儲存互相不綁死,任何一環都可以被替換。
這在 DuckDB、Photon 這種緊密整合的引擎上做不到,它們的優化器跟執行器綁死,想換掉執行器等於重寫半個 DuckDB。

LLVM 類比

DataFusion 的 SIGMOD 2024 論文 §4.1(論文連結)特別花一段講 LLVM,一開始看不太懂為什麼要類比編譯器,但這個類比其實非常準。

LLVM 出現之前: 每個編譯器都是前端後端綁死。GCC 想支援一個新語言,得從 parser 一路寫到 x86 code generator;想支援一個新 CPU 架構,得為每個既有語言各寫一次 backend。做 N 個語言 × M 個架構 = N × M 份工。

LLVM 出現之後: 中間插一個 IR(Intermediate Representation),前端只負責把源碼變成 IR,backend 只負責把 IR 變成機器碼。於是 Rust、Swift、Julia 全部共用同一個 x86 / ARM / RISC-V backend,N + M 就夠。

查詢引擎的類比是同構的:

DataFusion 之前(緊密整合時代):Spark 有自己的執行器、Presto 有自己的執行器、DuckDB 有自己的執行器,每個都要各寫一次向量化、各接一次 SSD、各支援一次 Iceberg。

DataFusion 之後:把 physical plan 當 IR,Spark 前端(Comet)、Ballista 分散式排程、你自己寫的 DataFrame API 都可以送 plan 進來,共用同一套向量化執行、同一套 memory pool、同一套 spill 機制。

這就是「1+1+1>3」的第一個支點:DataFusion 不是要贏 Spark,是要當 Spark 底下那塊可以被替換的執行引擎。Spark 的分析、優化、AQE 都留著,只把最後執行那段換成 DataFusion,這正是 Comet 在做的事。

為什麼緊密整合的引擎不夠

有個直覺的反駁:緊密整合的引擎(Photon、DuckDB)在自己的場景明明打得很好,為什麼要模組化?

因為模組化不是為了要跑得更快,是為了同一份執行引擎能在多少地方被重用。
這是一個生態問題,不是效能問題。

想像三個實際案例:

  1. Spark 想加速 SQL 執行:如果沒有 DataFusion,Databricks 得自己從頭寫 Photon(他們也真的寫了,還花了幾年),成本是幾十個 SIGMOD 級工程師 × 幾年
  2. 一家新創想做 lakehouse:不想從頭寫執行引擎,cargo add datafusion 一句話搞定,可以把時間花在自己的差異化上(例如某個特定的分析場景、某個特定的資料源)
  3. 一個資料庫想加入 Arrow 生態:如果引擎已經是 Arrow-native,接 Parquet、接 Iceberg、跟其他 Arrow-based 系統交換資料都零拷貝

緊密整合的引擎每次都要為新場景重寫一次,可嵌入引擎寫一次全部通吃。這在硬體變快、儲存格式標準化(Parquet、Iceberg)、Arrow 統一記憶體佈局之後,變成一個非常划算的取捨。

那為什麼是現在

DataFusion 不是第一個想做可嵌入引擎的專案,Postgres FDW、Calcite 都試過類似的事,但為什麼是 2020 年之後才真的長出來?

三個條件同時到位:

Arrow 標準化了記憶體佈局。 D1 講過這件事的重要性,如果想跨語言、跨 process 交換欄式資料,得先有個共同的 in-memory layout。在 Arrow 之前每個系統都自己排 buffer,Arrow 之後大家都吃同一份,這是可嵌入引擎能存在的前提。

Parquet + Iceberg 標準化了儲存。 D9–D12 走完的整條漏斗,都是規格層而不是實作層的東西。當儲存標準化了,引擎才能不管資料是誰寫的,只要對面吐出來的是 Parquet、metadata 是 Iceberg,就有辦法讀。

Rust 讓底層系統可以又快又安全。 C++ 快但難寫難維護(Photon 就是這條路,只有 Databricks 這種規模養得起),Java / Scala 生態成熟但有 JVM 稅(Spark 就是這條路),Rust 卡在中間,async、borrow checker、cargo 生態成熟到可以撐住 DataFusion 這種底層系統。這也是為什麼 Velox(Meta)走 C++、DataFusion 走 Rust,兩條路線都存在。

三個條件單獨都不新,湊在一起才有一個可嵌入的欄式執行引擎這個 niche。

總結!

今天先把為什麼再做一個引擎講明白,答案不是因為以前的不夠快,而是以前的都是整套綁死的,把中間那段抽出來當可替換元件,整個生態的性價比會改變。
DataFusion 是那個可替換元件,Arrow / Parquet / Iceberg 是它可以接進來的其他標準元件,Comet 是它跟 Spark 的膠水。

明天 D14 插一天論文導讀,讀 Leis 那篇 SIGMOD 2014 的 Morsel-Driven Parallelism,它是 2014 年寫的,卻是 DataFusion 並行執行的理論骨架。

留一個沒有標準答案的問題:
LLVM 的 IR 可以讓 Rust、Swift、Julia 共用同一個 backend;DataFusion 的 physical plan 也想扮演同樣的角色,可是 Substrait 才是那個「明著要當跨語言 IR」的規格,DataFusion physical plan 只是 Rust 內部的 struct。
為什麼 Comet 選了 protobuf 自訂格式,而不是 Substrait 這個標準?IR 的抽象層級、表達式集合的封閉性、runtime state(記憶體、排程)能不能一起搬——你會怎麼想這個 trade-off?

那就明天見~

參考資料


上一篇
Day 12 Iceberg 怎麼刪一列:從 delete file 到 deletion vector
下一篇
Day 14 Morsel-Driven Parallelism:DataFusion 多核並行與 work-stealing
系列文
1+1+1>3 ~ Spark 與 DataFusion、Comet 效能煉金術 ~21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言